#include "stdafx.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#include "fileThread.h"
#include "ini.h"
#include "main.h"
#include "filelist.h"
#include "exception.h"
#include "log.h"

/* FileThread */

FileThread::FileThread(CommandParams *_cp, Ini *_ini, wxTaskBarIcon *_tbIcon)
	: cp(_cp), ini(_ini), tbIcon(_tbIcon), wxThread(wxTHREAD_JOINABLE)
{
}

bool FileThread::myIsActive()
{
	return _myIsActive;
}

void* FileThread::Entry()
{
	myOut("in FileThread::OnEntry");
	//wxLog::EnableLogging(false);
	_myIsActive = true;

	wxString sDestination(cp->sDestination), sDT, log;
	try
	{
		for( unsigned int i = 0; i < ini->sl->GetCount(); i++ )
		{
			cp->sSource = ini->sl->Item(i);
			cp->sDestination = sDestination;
			if( cp->sSource == cp->sDestination )
			{
				Log::Info(wxT("\n%s \'from\' and \'to\' are the same (%s)"), err_str, cp->sSource.c_str().AsWChar());
				continue;
			}
			if( cp->bIFPath )
			{
				cp->sDestination += wxT("\\");
				const wxChar *c = cp->sSource.c_str();
				while( *c )
				{
					if( *c == '\\' || *c == '/' )
						cp->sDestination += wxT("-");
					else if( *c != ':' )
						cp->sDestination += *c;
					++c;
				}
			}
			if( cp->bVerbose )
			{
				wxString tst;
				tst.Printf(wxT("\nstarted at %s"), wxNow().c_str().AsWChar());
				Log::Info(tst);

				Log::Info(wxT("\nstarted at %s"), wxNow().c_str().AsWChar());
				Log::Info(wxT("syncing \'%s\' "), ini->sif->c_str().AsWChar());
				if( ini->sef->Length() )
					Log::Info(wxT("and not \'%s\' "), ini->sef->c_str().AsWChar());
				if( ini->sed->Length() )
					Log::Info(wxT("and not in \'%s\' "), ini->sed->c_str().AsWChar());
				Log::Info(wxT("  from \'%s\' to \'%s\'"), cp->sSource.c_str().AsWChar(), cp->sDestination.c_str().AsWChar());
			}
			myOut("creating LocalFiles");
			LocalFiles* lf = new LocalFiles(cp, cp->sSource, this);
			LocalFiles *bf = new LocalFiles(cp, cp->sDestination, this, true);
			myOut("done");
			try
			{
				myOut(cp->sSource.c_str());
				myOut(cp->sDestination.c_str());
				log.sprintf(_T("getting \'%s\' files info"), bf->sPath.c_str().AsWChar());
				if( cp->bVerbose )
				{
					Log::Info(log);
				}
				else
					myOut(log.c_str());
				//wxGetApp().setState(log);
				wxMutexGuiEnter();
				tbIcon->SetIcon(*icon1, log);
				wxMutexGuiLeave();
				checkTerminated();
				bf->FillFilesInfo();
				if( cp->bVerbose )
				{
					Log::Info(_T(" %i files"), bf->GetCount());
				}

				checkTerminated();

				log.sprintf(_T("getting \'%s\' files info"), lf->sPath.c_str().AsWChar());
				if( cp->bVerbose )
				{
					Log::Info(log);
				}
				else
					myOut(log.c_str());
				wxMutexGuiEnter();
				tbIcon->SetIcon(*icon1, log);
				wxMutexGuiLeave();
				checkTerminated();
				lf->FillFilesInfo();
				myOut("done");
				if( cp->bVerbose )
				{
					Log::Info(_T(" %i files"), lf->GetCount());
				}
				checkTerminated();

				if( cp->sSync == Ini::restore )
				{
					// perfoming restore
					log.sprintf(wxT("restoring files"));
					if( cp->bVerbose )
					{
						Log::Info(log);
					}
					else
						myOut(log.c_str());
					wxMutexGuiEnter();
					tbIcon->SetIcon(*icon2, log);
					wxMutexGuiLeave();
					//wxGetApp().setState(log);
					checkTerminated();
					bf->Add(lf, true);
					myOut(" done");

					if( cp->bVerbose )
					{
						Log::Info(_T(" %i files"), lf->GetCount());
					}
				}

				checkTerminated();

				if( cp->sSync == Ini::backup )
				{
					// performing backup
					if( cp->bDelete )
					{
						log.sprintf(_T("deleting from \'%s\'"), cp->sDestination.c_str().AsWChar());
						if( cp->bVerbose )
						{
							Log::Info(log);
						}
						else
							myOut(log.c_str());
						wxMutexGuiEnter();
						tbIcon->SetIcon(*icon2, log);
						wxMutexGuiLeave();
						//wxGetApp().setState(log);
						checkTerminated();
						bf->Remove(lf, true);
						if( cp->bVerbose )
						{
							Log::Info(_T(" %i files"), bf->GetCount());
						}
						myOut(" done");
					}

					checkTerminated();
					
					log.sprintf(wxT("backuping files"));
					if( cp->bVerbose )
					{
						Log::Info(log);
					}
					else
						myOut(log.c_str());

					wxMutexGuiEnter();
					tbIcon->SetIcon(*icon2, log);
					wxMutexGuiLeave();
					checkTerminated();
					DWORD bw = bf->Add(lf, true);
					if( cp->bVerbose )
					{
						Log::Info(_T(" %i files, %i bytes written"), bf->GetCount(), bw);
					}
					myOut(" done");
				}
				delete bf;
				delete lf;
			}
			catch(Exception &ex)
			{
				delete bf;
				delete lf;
				throw;
			}
		}
	}
	catch(Exception &ex)
	{
		Log::Info(wxT("\n\n%s %s"), err_str, ex.sMessage.c_str().AsWChar());
	}
	catch(...)
	{
		Log::Info(wxT("\n\n%s unknown error"), err_str);
	}
	
	//wxLog::EnableLogging(true);

	Log::Info(_T("done at %s\n"), wxNow().c_str().AsWChar());
	
	myOut("out FileThread::OnEntry");
	_myIsActive = false;
	return NULL;
}

void FileThread::OnExit()
{
	myOut("in FileThread::OnExit");
	wxGetApp().closeMainFrame();
	myOut("FileThread::OnExit out");
}

void FileThread::checkTerminated(void)
{
	if( TestDestroy() )
	{
		terminate_thread = true;
		wxMutexGuiEnter();
		tbIcon->SetIcon(*icon1, wxT("stopping at user request"));
		wxMutexGuiLeave();
		throw Exception(_T("cancelled at user request"));
	}
}
